{# ----------------------------------------------------------------------------
 # SymForce - Copyright 2022, Skydio, Inc.
 # This source code is under the Apache 2.0 license found in the LICENSE file.
 # ---------------------------------------------------------------------------- #}

{%- import "../util/util.jinja" as util with context -%}

#include <sym/{{ camelcase_to_snakecase(cls.__name__) }}.h>

namespace sym {

// Print implementations
{% for scalar in scalar_types %}
std::ostream& operator<<(std::ostream& os, const {{ cls.__name__ }}{{ scalar[0] }}& a) {
  const Eigen::IOFormat fmt(Eigen::StreamPrecision, Eigen::DontAlignCols, ", ", "\n", "[", "]");
  os << "<{{ cls.__name__ }}{{ scalar[0] }} " << a.Data().transpose().format(fmt) << ">";
  return os;
}
{% endfor %}

}  // namespace sym

{% if custom_generated_methods %}
// --------------------------------------------------------------------------
// Custom generated methods
// --------------------------------------------------------------------------

{% endif %}
{% for spec in custom_generated_methods %}
template <typename Scalar>
{# Return values from methods are const - https://github.com/symforce-org/symforce/issues/312 #}
const {{ util.method_declaration_custom_namespace(spec, namespace="sym::{}<Scalar>".format(cls.__name__), is_declaration=False) }} {
  {{ util.expr_code(spec) }}
}

{% endfor %}

{# {% for scalar in scalar_types %}
extern template struct sym::{{ camelcase_to_snakecase(cls.__name__) }}::StorageOps<{{ scalar }}>;
extern template struct sym::{{ camelcase_to_snakecase(cls.__name__) }}::GroupOps<{{ scalar }}>;
extern template struct sym::{{ camelcase_to_snakecase(cls.__name__) }}::LieGroupOps<{{ scalar }}>;
extern template struct sym::StorageOps<{{ scalar }}>;
extern template struct sym::GroupOps<{{ scalar }}>;
extern template struct sym::LieGroupOps<{{ scalar }}>;
{% endfor %} #}

// Explicit instantiation
{% for scalar in scalar_types %}
template class sym::{{ cls.__name__ }}<{{ scalar }}>;
{% endfor %}
